Android – 内存泄漏
前言
又是一个经常听到的概念,又是一时忍不住想去了解它。内存泄露,即部分对象虽然已经不在使用,但是因为有root持有引用,所以并没有销毁,所占用的内存一直没有被释放。简单的来说就是程序在向系统申请分配内存空间后,在使用完毕后未释放,结果导致一直占据该内存单元。一两次发生影响不大,如果频繁发生,那么可用内存会逐渐不足,最终在某一次请求内存的时候发现内存不足而OOM(内存溢出:程序向系统申请的内存空间超出了系统能给的)。这里要明确一个概念,只有强引用会发生内存泄露,而弱引用因为其特殊机制,所以影响不大。(什么是强弱引用???我也不知道耶,QAQ 逃!先Mark下!下面会讲到。
Java 垃圾回收机制
这又是一个值得深入理解的一个概念,引用他人的见解,文末会给出引用链接。在大部分虚拟机(包括Android的ART)中,Java都采用了“可达性分析”算法来进行内存回收,原理是:会有几个引用作为root节点,对于任意对象来说,如果从root层层遍历,如果找不到对于他的引用链,那么这个对象就被标记为无用,就会在GC时被销毁。垃圾回收用于释放不可达的对象所占据的内存。
内存
JAVA是在JVM所虚拟出的内存环境中运行的,JVM的内存可以分为三个区:堆(heap),栈(stack)和方法区(method)。
- 栈:先进后出
- 堆:堆内存用来存放有new创建的对象和数组
- 方法区:又叫静态区,包含所有的class和static变量
引用类型
- 强引用(Strong reference)
最常见的一种引用类型,常见形式如:A a = new A(); 。强引用本身存储在栈内存中,其存储指向对内存中对象的地址。一般情况下,当对内存中的对象不再有任何强引用指向它时,垃圾回收机器开始考虑可能要对此内存进行垃圾回收。如当进行a=null,此时,刚刚在堆中分配地址并新建的a对象没有其他的任何引用,当系统进行辣鸡回收时,堆内存将会被垃圾回收。
- 软引用(Soft reference)
软引用所指示的对象进行垃圾回收需要满足以下两个条件:
(1):当前指示的对象没有任何强引用指向它;
(2):虚拟机内存不足
- 弱引用(Weak reference)
软引用不改变原有强引用对象的垃圾回收时机,一旦其指示对象没有任何强引用对象时,此对象即进入正常的垃圾回收流程。
- 虚引用(Phantom reference)
虚引用只有一个构造函数,不管有无强引用指向虚引用的指示对象,虚引用的get()方法返回结果都是null,虚引用并不会改变其指示对象的垃圾回收时机。
内存泄露原因
如果持有对象的强引用,垃圾回收是无法在内存中回收这个对象,对象无法被GC回收就是造成内存泄露的原因。